﻿using System.Collections.Generic;
using Sinacor.Infra.Service.Common;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.Service.Validation;
using Sinacor.Infra.Service.Validation.BusinessRules;

namespace Sinacor.Servico.Bovespa.Corretagem.BusinessLogic
{
    /// <summary>
    /// Logica de negÃ³cios de polÃ­tica de corretagem
    /// </summary>
    public class PoliticaCorretagem : BaseBusinessLogic
    {
        #region Atributos

        //Antigo
        private const int ERRO_POLITICACORRETAGEM_CALENDARIO = 000000;

        private int _erroObjetoNulo = 109529;
        ResourceAccess.PoliticaCorretagem _raPoliticaCorretagem = null;

        #endregion

        #region Construtor

        /// <summary>
        /// Construtor PoliticaCorretagem
        /// </summary>
        public PoliticaCorretagem()
            : base()
        {
            this._raPoliticaCorretagem = new ResourceAccess.PoliticaCorretagem();
        }

        #endregion

        #region Propriedades

        /// <summary>
        /// Objeto Nulo
        /// </summary>
        public int ErroObjetoNulo
        {
            get
            {
                return _erroObjetoNulo;
            }
            set
            {
                _erroObjetoNulo = value;
            }
        }

        #endregion

        #region MÃ©todos

        /// <summary>
        /// Consulta polÃ­ticas de corretagem conforme filtro.
        /// </summary>
        /// <param name="entity"></param>
        public List<BusinessEntity.PoliticaCorretagem> ConsultarPoliticasCorretagens(BusinessEntity.Parameter.FiltroPoliticaCorretagem entity)
        {
            if (entity != null)
            {
                return this._raPoliticaCorretagem.ConsultarPoliticasCorretagens(entity);
            }
            else
            {
                throw new BusinessException(ErroObjetoNulo);
            }
        }

        /// <summary>
        /// Obtem uma politica de corretagem
        /// </summary>
        /// <param name="entity"></param>
        public BusinessEntity.PoliticaCorretagem ObterPoliticaCorretagem(BusinessEntity.Parameter.FiltroPoliticaCorretagemChave entity)
        {
            BusinessEntity.PoliticaCorretagem politicaCorretagem = null;

            if (entity != null)
            {
                SinacorValidation validation = null;

                //Validacao de RulesSets
                validation = new SinacorValidation();
                validation.Validate<BusinessEntity.Parameter.FiltroPoliticaCorretagemChave>(entity);
                validation.Validate();

                //Obtem Politica de Corretagem
                politicaCorretagem = this._raPoliticaCorretagem.ObterPoliticaCorretagem(entity);

                if (politicaCorretagem.TabelaPadrao != null &&
                    politicaCorretagem.TabelaPadrao.Codigo != null)
                {
                    //Obtém Tabela de corretagem padrao
                    politicaCorretagem.TabelaPadrao = new BusinessLogic.TabelaCorretagem().ObterTabelaCorretagem(
                        new BusinessEntity.Parameter.FiltroTabelaCorretagemChave
                        {
                            Codigo = politicaCorretagem.TabelaPadrao.Codigo.Value
                        });
                }                

                if (politicaCorretagem.TabelaPadrao != null && politicaCorretagem.TabelaBeneficio != null && politicaCorretagem.TabelaPadrao.Codigo == politicaCorretagem.TabelaBeneficio.Codigo)
                {
                    politicaCorretagem.TabelaBeneficio = politicaCorretagem.TabelaPadrao;
                }
                else
                {
                    if (politicaCorretagem.TabelaBeneficio != null &&
                        politicaCorretagem.TabelaBeneficio.Codigo != null)
                    {
                        //Obtem Tabela de corretagem de Beneficio
                        politicaCorretagem.TabelaBeneficio = new BusinessLogic.TabelaCorretagem().ObterTabelaCorretagem(
                            new BusinessEntity.Parameter.FiltroTabelaCorretagemChave
                            {
                                Codigo = politicaCorretagem.TabelaBeneficio.Codigo.Value
                            });
                    }                    
                }

                //Obtem tipo Aplicacao Politica
                politicaCorretagem = ObterTipoAplicacaoPolitica(politicaCorretagem);

                return politicaCorretagem;
            }
            else
            {
                throw new BusinessException(ErroObjetoNulo);
            }
        }

        private BusinessEntity.PoliticaCorretagem ObterTipoAplicacaoPolitica(BusinessEntity.PoliticaCorretagem politicaCorretagem)
        {
            if (politicaCorretagem.TipoAplicacao != null)
            {
                politicaCorretagem.TipoAplicacao = new BusinessLogic.TipoAplicacaoPolitica().ObterTipoAplicacaoPolitica(
                new BusinessEntity.Parameter.FiltroTipoAplicacaoPoliticaChave
                {
                    Codigo = politicaCorretagem.TipoAplicacao.Codigo.Value
                });
            }            

            if (politicaCorretagem.TipoControleBeneficio != BusinessEntity.Enum.TipoControleBeneficio.Nao)
            {
                politicaCorretagem.Beneficios = new BusinessLogic.ControleBeneficio().ConsultarControlesBeneficios(
                    new BusinessEntity.Parameter.FiltroControleBeneficio
                    {
                        CodigoPolitica = politicaCorretagem.Codigo,
                        DataInicial = politicaCorretagem.DataInicial
                    });

                if (politicaCorretagem.EfetuarVerificacao == true)
                {
                    politicaCorretagem = ConsultarVerificacoesPoliticas(politicaCorretagem);
                }
            }
            else
            {
                if (politicaCorretagem.EfetuarVerificacao == true)
                {
                    politicaCorretagem = ConsultarVerificacoesPoliticas(politicaCorretagem);
                }
            }
            return politicaCorretagem;
        }

        private BusinessEntity.PoliticaCorretagem ConsultarVerificacoesPoliticas(BusinessEntity.PoliticaCorretagem politicaCorretagem)
        {
            politicaCorretagem.Verificacoes = new BusinessLogic.VerificacaoPolitica().ConsultarVerificacoesPoliticas(
                new BusinessEntity.Parameter.FiltroVerificacaoPolitica
                {
                    CodigoPolitica = politicaCorretagem.Codigo,
                    DataInicial = politicaCorretagem.DataInicial
                });

            return politicaCorretagem;
        }
        /// <summary>
        /// Exclui uma polÃ­tica de corretagem
        /// </summary>
        /// <param name="entity"></param>
        public void ExcluirPoliticaCorretagem(BusinessEntity.Parameter.FiltroPoliticaCorretagemChave entity)
        {
            BusinessRulesValidator validador = null;
            BusinessRuleValidation.ValidaExclusaoPoliticaCorretagem verificaExclusaoPoliticaCorretagem = null;

            if (entity != null)
            {
                verificaExclusaoPoliticaCorretagem = new BusinessRuleValidation.ValidaExclusaoPoliticaCorretagem();
                verificaExclusaoPoliticaCorretagem.EntityToValidate = entity;
                validador = new BusinessRulesValidator();
                validador.AddValidation("VerificaExclusaoPoliticaCorretagem", verificaExclusaoPoliticaCorretagem);

                validador.Validate();

                new BusinessLogic.ControleBeneficio().ExcluirTodosBeneficiosPolitica(
                    new BusinessEntity.Parameter.FiltroControleBeneficioChave
                    {
                        CodigoPolitica = entity.Codigo,
                        DataInicial = entity.DataInicial
                    });

                new BusinessLogic.VerificacaoPolitica().ExcluirTodasVerificacoesPolitica(
                    new BusinessEntity.Parameter.FiltroVerificacaoPolitica
                    {
                        CodigoPolitica = entity.Codigo,
                        DataInicial = entity.DataInicial
                    });

                this._raPoliticaCorretagem.ExcluirPoliticaCorretagem(entity);
                
            }
            else
            {
                throw new BusinessException(ErroObjetoNulo);
            }
        }

        /// <summary>
        /// Duplica uma polÃ­tica de corretagem bem como suas entidades dependencias.
        /// </summary>
        /// <param name="entity"></param>
        public BusinessEntity.PoliticaCorretagem DuplicarPoliticaCorretagem(BusinessEntity.Parameter.FiltroPoliticaCorretagemChave entity)
        {
            SinacorValidation validation = null;
            BusinessEntity.PoliticaCorretagem novaPolitica = null;

            if (entity != null)
            {
                //ValidaÃ§Ã£o de RulesSets
                validation = new SinacorValidation();
                validation.Validate<BusinessEntity.Parameter.FiltroPoliticaCorretagemChave>(entity);
                validation.Validate();

                //Duplica polÃ­tica de Corretagem
                novaPolitica = this.ObterPoliticaCorretagem(this._raPoliticaCorretagem.DuplicarPoliticaCorretagem(entity));

                //Duplica controle de BenefÃ­cios
                new BusinessLogic.ControleBeneficio().DuplicarControlesBeneficiosPolitica(
                    new BusinessEntity.Parameter.FiltroPoliticaCorretagemChave
                    {
                        Codigo = entity.Codigo,
                        DataInicial = entity.DataInicial
                    }
                    ,ref novaPolitica);

                //Duplica as verificaÃ§Ãµes
                new BusinessLogic.VerificacaoPolitica().DuplicarVerificacoesPolitica(
                    new BusinessEntity.Parameter.FiltroPoliticaCorretagemChave
                    {
                        Codigo = entity.Codigo,
                        DataInicial = entity.DataInicial
                    }
                    , ref novaPolitica);

                return novaPolitica;
            }
            else
            {
                throw new BusinessException(ErroObjetoNulo);  
            }
        }

        /// <summary>
        /// Inclui uma nova polÃ­tica de corretagem
        /// </summary>
        /// <param name="entity"></param>
        public void IncluirPoliticaCorretagem(BusinessEntity.PoliticaCorretagem entity)
        {
            BusinessRulesValidator validador = null;
            BusinessRuleValidation.ValidaInclusaoPoliticaCorretagem verificaInclusaoPoliticaCorretagem = null;

            if (entity != null)
            {
                verificaInclusaoPoliticaCorretagem = new BusinessRuleValidation.ValidaInclusaoPoliticaCorretagem();
                verificaInclusaoPoliticaCorretagem.EntityToValidate = entity;
                validador = new BusinessRulesValidator();
                validador.AddValidation("ValidaInclusaoPoliticaCorretagem", verificaInclusaoPoliticaCorretagem);

                validador.Validate();

                if (this._raPoliticaCorretagem.VerificarExistenciaPolitica(new BusinessEntity.Parameter.FiltroPoliticaCorretagemChave
                {Codigo = entity.Codigo}))
                {
                    this._raPoliticaCorretagem.AjustarUltimaPoliticaCorretagem(new BusinessEntity.Parameter.FiltroPoliticaCorretagemChave 
                    {Codigo = entity.Codigo, DataInicial = entity.DataInicial});

                    InclusaoPoliticaCorretagem(entity);
                }
                else
                {
                    InclusaoPoliticaCorretagem(entity);

                    if (entity.TipoControleBeneficio != BusinessEntity.Enum.TipoControleBeneficio.Nao)
                    {
                        this.RelacionarBeneficiosComPolitica(ref entity);

                        new BusinessLogic.ControleBeneficio().IncluirControlesBeneficios(entity.Beneficios);

                        EfetuarVerificacaoInclusao(entity);

                    }
                    else
                    {
                        EfetuarVerificacaoInclusao(entity);
                    }
                }
            }
            else
            {
                throw new BusinessException(ErroObjetoNulo);  
            }
        }

        private void EfetuarVerificacaoInclusao(BusinessEntity.PoliticaCorretagem entity)
        {
            if (entity.EfetuarVerificacao == true)
            {
                //Relaciona a polÃ­tica de corretagem
                this.RelacionarVerificacoesComPolitica(ref entity);

                //Inclui verificaÃ§Ãµes da polÃ­tica de corretagem
                new BusinessLogic.VerificacaoPolitica().IncluirVerificacoesPoliticas(entity.Verificacoes);

            }
        }

        private void InclusaoPoliticaCorretagem(BusinessEntity.PoliticaCorretagem entity)
        {
            this._raPoliticaCorretagem.IncluirPoliticaCorretagem(entity);
        }

        /// <summary>
        /// Relaciona o codigo e dada inicial da polÃ­tica de corretagem com cada um dos
        /// controles de beneficios contidos na propriedade "Beneficios" da entidade
        /// informada.
        /// </summary>
        /// <param name="entity"></param>
        private void RelacionarBeneficiosComPolitica(ref BusinessEntity.PoliticaCorretagem entity)
        {
            if (entity.TipoControleBeneficio != BusinessEntity.Enum.TipoControleBeneficio.Nao)
            {
                foreach (BusinessEntity.ControleBeneficio item in entity.Beneficios)
                {
                    item.CodigoPolitica = entity.Codigo;
                    item.DataInicial = entity.DataInicial;
                }
            }
        }

        /// <summary>
        /// Relaciona o codigo e a data inicial da politica de corretagem com todas as
        /// entidade de verificaÃ§Ã£o contidas na propriedade "Verificacoes" da mesma
        /// </summary>
        /// <param name="entity"></param>
        private void RelacionarVerificacoesComPolitica(ref BusinessEntity.PoliticaCorretagem entity)
        {
            if (entity.EfetuarVerificacao.Value)
            {
                foreach (BusinessEntity.VerificacaoPolitica item in entity.Verificacoes)
                {
                    item.CodigoPolitica = entity.Codigo;
                    item.DataInicial = entity.DataInicial;
                }
            }
        }

        /// <summary>
        /// Altera uma polÃ­tica de corretagem
        /// </summary>
        /// <param name="entity"></param>
        public void AlterarPoliticaCorretagem(BusinessEntity.PoliticaCorretagem entity)
        {
            BusinessRulesValidator validador = null;
            BusinessRuleValidation.ValidaAlteracaoPoliticaCorretagem verificaAlteracaoPoliticaCorretagem = null;

            if (entity != null)
            {
                verificaAlteracaoPoliticaCorretagem = new BusinessRuleValidation.ValidaAlteracaoPoliticaCorretagem();
                verificaAlteracaoPoliticaCorretagem.EntityToValidate = entity;
                validador = new BusinessRulesValidator();
                validador.AddValidation("ValidaAlteracaoPoliticaCorretagem", verificaAlteracaoPoliticaCorretagem);

                validador.Validate();

                this._raPoliticaCorretagem.AlterarPoliticaCorretagem(entity);

                new BusinessLogic.ControleBeneficio().ExcluirTodosBeneficiosPolitica(new BusinessEntity.Parameter.FiltroControleBeneficioChave
                {
                    CodigoPolitica = entity.Codigo,
                    DataInicial = entity.DataInicial
                });

                if (entity.TipoControleBeneficio != BusinessEntity.Enum.TipoControleBeneficio.Nao)
                {
                    this.RelacionarBeneficiosComPolitica(ref entity);

                    new BusinessLogic.ControleBeneficio().IncluirControlesBeneficios(entity.Beneficios);

                    EfetuarVerificaoAlteracao(entity);
                }
                else
                {
                    EfetuarVerificaoAlteracao(entity);
                }
            }
            else
            {
                throw new BusinessException(ErroObjetoNulo);  
            }
        }

        private void EfetuarVerificaoAlteracao(BusinessEntity.PoliticaCorretagem entity)
        {
            if (entity.EfetuarVerificacao == true)
            {
                //Relacionar as verificaÃ§Ãµes com a polÃ­tica de Corretagem
                this.RelacionarVerificacoesComPolitica(ref entity);

                //Atualizar lista de VerificaÃ§Ãµes
                new BusinessLogic.VerificacaoPolitica().AtualizarVerificacoesPolitica(entity.Verificacoes);
            }
        }

        #endregion 

        #region MÃ©todos Antigos

        /// <summary>
        /// MÃ©todo ValidarCalendarioPoliticaCorretagem
        /// </summary>
        public void ValidarCalendarioPoliticaCorretagem(BusinessEntity.PoliticaCorretagem politicacorretagem)
        {
            //Verificar implementaÃ§Ã£o 
            throw new BusinessException(ERRO_POLITICACORRETAGEM_CALENDARIO);
        }

        #endregion
    }
}